惊了!同事竟然在代码里“下毒”
写这个文章是因为前段时间确实因为公司的业务开发太忙太紧,所有开发都处在于加班赶项目,并且加入的新人较多造成了一系列代码不可控的质量问题。
文章针对这段时间代码出现的各种各样的问题进行了一个概况和整理,主要集中在代码编码的问题,抽象化的问题,还有就是涉及到微服务中调用和编写接口的问题。
其实按道理来说,这些应该属于编程的基本功,貌似不太值得写一篇文章,不过倒是可以通过这些基本功的出发,去讨论一个代码编程系统构建的一个本质,所以还是比较值得去展开。
大概先铺垫下,会按照一个原则和建议来展开一个一个的进行讨论。
编码的问题
避免过多的 IF 嵌套
所谓的“箭头形”代码基本都是因为大量的 IF 嵌套导致,一方面形成一个深深的箭头形状,在阅读代码造成缩进夸张的语句块。
其实对应 IF-ELSE 过长的主要原因无非就是对当前状态进行检查并决定继续还是跳转。
①使用卫语句(Guard Clauses)提前返回,避免层层嵌套
先对 IF/ELSE 的逻辑结构进行一些分析,我们基本上有两种用法:
"优先考虑满足条件,进行处理流程",代码如下:
if(user.getId() == 10){
//满足条件,执行
}else{
//不满足条件,退出
}
if(user.getId() != 10){
//不满足条件,退出
}else{
//满足条件,执行
}
这是两个不同的逻辑结构,他们都可以写出同样的代码逻辑,但是在第一种中,如果代码量增大,嵌套增多,就很容易在条件中迷失了方向。
②规划好判断条件和状态模型
如果是业务允许其实是可以将多个判断条件进行整合,这样可以避免箭头形代码的出现。
但是仅仅一段 IF 条件判断的语句又变得非常的臃肿一行都放不下,如果出现了非常复杂多状态判断和组合,可以使用“状态表”,或者是状态机等设计模式来进行解耦。
③将 IF 中的业务细节进行抽象成函数
将 IF 中繁琐的业务细节抽成函数,一方面可以减少又长又臭的代码,更利于屏蔽细节,将不关流程的业务逻辑锁定在一个特定的区域。
谨慎多层循环嵌套中的操作
例如,这段代码总共经历了 4 层的循环,如果循环是 10x10x10x10,那么最终的 DB 操作是要经历单独的开销 10000 次。
第一,这 10000 次开销如果是程序员在写代码已经明确知道的开销属于业务必须那倒无妨,只怕程序员在写代码的时候还无意识到这个点是会被随时放大。
第二,即使 10000 次开销是属于业务必须,那按照这个代码来看,还是存在可以优化的空间,可以在循环中将所有查询条件都进行拼凑,然后在进行一定程度的批量查询,可以较大程度降低 DB 的开销。
不要随意定义局部变量名
命名风格我们可以参考阿里的《Java开发手册》,这里主要指出来的是局部变量随意命名的现象比较严重,大家一般都会以为局部变量只是在本方法内使用,又不会对其他方法和其他人造成影响。
变量名 ma 和 map 没有本身含义,并且他们的泛类又是一样,很难保证不会再下面的代码不小心使用错误。
避免又臭又长的类和方法
一点都不夸张,之前看到过一类一千多行,一个方法长达 300 行,IDE 大概一页正常来说 30-50 行(取决屏幕大小),这个叫阅读者怎么查看。
阅读的时候,不断的滚轮翻页,就算是原作者,恐怕时间一长也很难驾驭这个类,就不用说后来的维护者了。
更重要的是一个类,一个方法过长时,会严重阻碍你的扩展和修改,方法中每一个逻辑都牵扯到很多分散的上下文,会让修改和扩展异常困难。
按照《重构》所说,出现类过长的情况很多是职责不明确,一个类存在着几十个方法,那绝对是职责过多或职责不细分。
简单列一下针对又长又臭的重构处理:
分析需要重构类的功能。
将职责相同的方法使用组合或集成的方式抽取为独立的类。
分析各个方法,将重复的代码提取为函数。
命名,对类有一个好的命名有利于对类的定位和确立职责。
Log 日志要提供明确的指向,辅助定位
像以下的这个例子,打印了一个 log.error 日志,但这个错误,就算我们事后去查看日志,只知道这里有一个错误日志,但究竟是哪一个用户日志,哪一张优惠券的日志,无从得知,不能有助于我们直接定位错误。
通常,我们留下实体名字和逻辑关键字就足以识别一条记录。
复杂模块,代码未动,大纲注释先行
只要流程清晰,逻辑明朗,这个时候写代码其实是最简单的事情。
功能相同尽量抽象,不要发散式修改
举这次我们构建订单的一个例子,见下图:
微服务编码问题
RPC 接口必须是业务职责
之前就发现有部分同学把 RPC 接口定义成:
insertXXX
updateXXX
listXXX
严禁循环调用 RPC 接口
与项目内编程不同的是,每个 RPC 接口的调用都会伴随着一次的网络开销,需要需要对一个接口进行反复请求,这个时候可以要求 RPC 接口的提供方另外提供一个可以批量的接口,将单次反复的请求变成一次请求,减少网络开销。
使用工具辅助清理恶性代码
P3C 插件
在使用 Eclipse 或 idea 编程中,首推使用阿里的 P3C 插件进行辅助,代码规范检查插件 P3C,是根据《阿里巴巴Java开发手册》转化而成的自动化插件。
使用 Skywalking 找出恶性代码
小结
在分享的时候其实还讲了抽象的原则和一些设计模式的使用,这里就不累赘的复述了。
作者:陈于喆
简介:十余年的开发和架构经验,国内较早一批微服务开发实施者。曾任职国内互联网公司网易和唯品会高级研发工程师,后在创业公司担任技术总监/架构师。
编辑:陶家龙
征稿:有投稿、寻求报道意向技术人请联络 editor@51cto.com
精彩文章推荐:
Elasticsearch查询速度为什么这么快?
再有人问Kafka,别说你不会!
为了做到微服务的高可用,鬼知道我出了多少张牌